import os
import subprocess
import ast
import json
import tempfile
from typing import Dict, Any, List
try:
    from .utils import EnhancedOutput as Debug, OutputType as DebugType
except ImportError:
    from utils import EnhancedOutput as Debug, OutputType as DebugType

class CodeExecuteTool:
    name = "code_execute"
    description = "执行代码文件或代码片段，支持多种编程语言"
    parameters = {
        "type": "object",
        "properties": {
            "code": {
                "type": "string",
                "description": "要执行的代码内容"
            },
            "file_path": {
                "type": "string", 
                "description": "要执行的代码文件路径（可选，与code二选一）"
            },
            "language": {
                "type": "string",
                "description": "编程语言（python, javascript, java, cpp等）"
            },
            "timeout": {
                "type": "integer",
                "description": "执行超时时间（秒），默认30"
            }
        },
        "required": []
    }

    def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
        try:
            code = args.get("code")
            file_path = args.get("file_path")
            language = args.get("language", "python")
            timeout = args.get("timeout", 30)
            
            if not code and not file_path:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": "必须提供代码内容或文件路径"
                }
            
            if file_path:
                return self._execute_file(file_path, language, timeout)
            else:
                return self._execute_code(code, language, timeout)
                
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码执行失败: {str(e)}"
            }

    def _execute_file(self, file_path: str, language: str, timeout: int) -> Dict[str, Any]:
        """执行代码文件"""
        try:
            if not os.path.exists(file_path):
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": f"文件不存在: {file_path}"
                }
            
            # 检测语言
            if language == "auto":
                ext = os.path.splitext(file_path)[1].lower()
                language_map = {
                    '.py': 'python',
                    '.js': 'javascript', 
                    '.ts': 'typescript',
                    '.java': 'java',
                    '.cpp': 'cpp',
                    '.c': 'c',
                    '.go': 'go',
                    '.rs': 'rust'
                }
                language = language_map.get(ext, 'python')
            
            # 根据语言选择执行方式
            if language == 'python':
                return self._execute_python_file(file_path, timeout)
            elif language in ['javascript', 'node']:
                return self._execute_node_file(file_path, timeout)
            elif language == 'java':
                return self._execute_java_file(file_path, timeout)
            else:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": f"暂不支持执行 {language} 文件"
                }
                
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"执行文件失败: {str(e)}"
            }

    def _execute_code(self, code: str, language: str, timeout: int) -> Dict[str, Any]:
        """执行代码片段"""
        try:
            if language == 'python':
                return self._execute_python_code(code, timeout)
            elif language in ['javascript', 'node']:
                return self._execute_node_code(code, timeout)
            else:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": f"暂支持执行 {language} 代码片段"
                }
                
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"执行代码片段失败: {str(e)}"
            }

    def _execute_python_file(self, file_path: str, timeout: int) -> Dict[str, Any]:
        """执行Python文件"""
        try:
            result = subprocess.run(
                ['python', file_path],
                capture_output=True,
                text=True,
                encoding='utf-8',
                timeout=timeout,
                cwd=os.path.dirname(file_path)
            )
            
            return {
                "success": result.returncode == 0,
                "stdout": result.stdout,
                "stderr": result.stderr
            }
        except subprocess.TimeoutExpired:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码执行超时（{timeout}秒）"
            }

    def _execute_python_code(self, code: str, timeout: int) -> Dict[str, Any]:
        """执行Python代码片段"""
        try:
            # 语法检查
            try:
                ast.parse(code)
            except SyntaxError as e:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": f"语法错误: {str(e)}"
                }
            
            # 创建临时文件执行
            with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False, encoding='utf-8') as f:
                f.write(code)
                temp_file = f.name
            
            try:
                result = subprocess.run(
                    ['python', temp_file],
                    capture_output=True,
                    text=True,
                    encoding='utf-8',
                    timeout=timeout
                )
                
                return {
                    "success": result.returncode == 0,
                    "stdout": result.stdout,
                    "stderr": result.stderr
                }
            finally:
                os.unlink(temp_file)
                
        except subprocess.TimeoutExpired:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码执行超时（{timeout}秒）"
            }

    def _execute_node_file(self, file_path: str, timeout: int) -> Dict[str, Any]:
        """执行Node.js文件"""
        try:
            result = subprocess.run(
                ['node', file_path],
                capture_output=True,
                text=True,
                encoding='utf-8',
                timeout=timeout,
                cwd=os.path.dirname(file_path)
            )
            
            return {
                "success": result.returncode == 0,
                "stdout": result.stdout,
                "stderr": result.stderr
            }
        except subprocess.TimeoutExpired:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码执行超时（{timeout}秒）"
            }

    def _execute_node_code(self, code: str, timeout: int) -> Dict[str, Any]:
        """执行Node.js代码片段"""
        try:
            # 创建临时文件执行
            with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False, encoding='utf-8') as f:
                f.write(code)
                temp_file = f.name
            
            try:
                result = subprocess.run(
                    ['node', temp_file],
                    capture_output=True,
                    text=True,
                    encoding='utf-8',
                    timeout=timeout
                )
                
                return {
                    "success": result.returncode == 0,
                    "stdout": result.stdout,
                    "stderr": result.stderr
                }
            finally:
                os.unlink(temp_file)
                
        except subprocess.TimeoutExpired:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码执行超时（{timeout}秒）"
            }

    def _execute_java_file(self, file_path: str, timeout: int) -> Dict[str, Any]:
        """执行Java文件"""
        try:
            dir_path = os.path.dirname(file_path)
            file_name = os.path.splitext(os.path.basename(file_path))[0]
            
            # 编译
            compile_result = subprocess.run(
                ['javac', file_path],
                capture_output=True,
                text=True,
                encoding='utf-8',
                timeout=timeout,
                cwd=dir_path
            )
            
            if compile_result.returncode != 0:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": f"编译失败: {compile_result.stderr}"
                }
            
            # 执行
            run_result = subprocess.run(
                ['java', file_name],
                capture_output=True,
                text=True,
                encoding='utf-8',
                timeout=timeout,
                cwd=dir_path
            )
            
            return {
                "success": run_result.returncode == 0,
                "stdout": run_result.stdout,
                "stderr": run_result.stderr
            }
            
        except subprocess.TimeoutExpired:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码执行超时（{timeout}秒）"
            }

class CodeValidateTool:
    name = "code_validate"
    description = "验证代码语法和基本错误检查"
    parameters = {
        "type": "object",
        "properties": {
            "code": {
                "type": "string",
                "description": "要验证的代码内容"
            },
            "file_path": {
                "type": "string",
                "description": "要验证的代码文件路径（可选）"
            },
            "language": {
                "type": "string",
                "description": "编程语言（python, javascript, java等）"
            }
        },
        "required": []
    }

    def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
        try:
            code = args.get("code")
            file_path = args.get("file_path")
            language = args.get("language", "python")
            
            if not code and not file_path:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": "必须提供代码内容或文件路径"
                }
            
            # 获取代码内容
            if file_path:
                with open(file_path, 'r', encoding='utf-8') as f:
                    code = f.read()
            
            # 检测语言
            if file_path and language == "auto":
                ext = os.path.splitext(file_path)[1].lower()
                language_map = {
                    '.py': 'python',
                    '.js': 'javascript',
                    '.ts': 'typescript',
                    '.java': 'java',
                    '.cpp': 'cpp',
                    '.c': 'c'
                }
                language = language_map.get(ext, 'python')
            
            # 根据语言进行验证
            if language == 'python':
                return self._validate_python(code)
            elif language in ['javascript', 'typescript']:
                return self._validate_javascript(code)
            elif language == 'java':
                return self._validate_java(code)
            else:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": f"暂不支持验证 {language} 代码"
                }
                
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码验证失败: {str(e)}"
            }

    def _validate_python(self, code: str) -> Dict[str, Any]:
        """验证Python代码"""
        try:
            # 语法检查
            try:
                ast.parse(code)
                syntax_valid = True
                syntax_error = ""
            except SyntaxError as e:
                syntax_valid = False
                syntax_error = f"语法错误 (行{e.lineno}): {e.msg}"
            
            # 检查常见问题
            issues = []
            lines = code.split('\n')
            
            for i, line in enumerate(lines, 1):
                # 检查未使用的导入（简单检查）
                if line.strip().startswith('import ') or line.strip().startswith('from '):
                    pass  # 这里可以添加更复杂的检查
                
                # 检查常见错误模式
                if 'print' in line and not line.strip().startswith('#'):
                    # 提醒在生产环境中移除print语句
                    if "console" not in line.lower():  # 排除相关的console print
                        pass
            
            result = []
            result.append(f"Python代码验证结果:")
            result.append(f"语法检查: {'✓ 通过' if syntax_valid else '✗ 失败'}")
            if syntax_error:
                result.append(f"  {syntax_error}")
            
            result.append(f"总行数: {len(lines)}")
            result.append(f"字符数: {len(code)}")
            
            return {
                "success": True,
                "stdout": "\n".join(result),
                "stderr": syntax_error if not syntax_valid else ""
            }
            
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"Python验证失败: {str(e)}"
            }

    def _validate_javascript(self, code: str) -> Dict[str, Any]:
        """验证JavaScript代码"""
        try:
            # 简单的JavaScript语法检查
            # 这里可以使用Node.js进行更准确的验证
            
            lines = code.split('\n')
            bracket_count = 0
            paren_count = 0
            brace_count = 0
            
            for i, line in enumerate(lines, 1):
                for char in line:
                    if char == '(':
                        paren_count += 1
                    elif char == ')':
                        paren_count -= 1
                    elif char == '[':
                        bracket_count += 1
                    elif char == ']':
                        bracket_count -= 1
                    elif char == '{':
                        brace_count += 1
                    elif char == '}':
                        brace_count -= 1
            
            syntax_valid = (bracket_count == 0 and paren_count == 0 and brace_count == 0)
            
            result = []
            result.append(f"JavaScript代码验证结果:")
            result.append(f"基础语法检查: {'✓ 通过' if syntax_valid else '✗ 失败'}")
            if not syntax_valid:
                result.append("  括号或大括号不匹配")
            
            result.append(f"总行数: {len(lines)}")
            result.append(f"字符数: {len(code)}")
            
            return {
                "success": True,
                "stdout": "\n".join(result),
                "stderr": "" if syntax_valid else "括号或大括号不匹配"
            }
            
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"JavaScript验证失败: {str(e)}"
            }

    def _validate_java(self, code: str) -> Dict[str, Any]:
        """验证Java代码"""
        try:
            # 基础的Java语法检查
            has_class = False
            has_main = False
            lines = code.split('\n')
            
            for line in lines:
                if 'class' in line and '{' in line:
                    has_class = True
                if 'public static void main' in line:
                    has_main = True
            
            result = []
            result.append(f"Java代码验证结果:")
            result.append(f"包含类定义: {'✓' if has_class else '✗'}")
            result.append(f"包含main方法: {'✓' if has_main else '✗'}")
            result.append(f"总行数: {len(lines)}")
            result.append(f"字符数: {len(code)}")
            
            return {
                "success": True,
                "stdout": "\n".join(result),
                "stderr": ""
            }
            
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"Java验证失败: {str(e)}"
            }

class CodeFormatTool:
    name = "code_format"
    description = "格式化代码，改善代码可读性"
    parameters = {
        "type": "object",
        "properties": {
            "code": {
                "type": "string",
                "description": "要格式化的代码内容"
            },
            "file_path": {
                "type": "string",
                "description": "要格式化的代码文件路径（可选）"
            },
            "language": {
                "type": "string",
                "description": "编程语言（python, javascript, json等）"
            },
            "indent_size": {
                "type": "integer",
                "description": "缩进大小，默认4"
            }
        },
        "required": []
    }

    def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
        try:
            code = args.get("code")
            file_path = args.get("file_path")
            language = args.get("language", "auto")
            indent_size = args.get("indent_size", 4)
            
            if not code and not file_path:
                return {
                    "success": False,
                    "stdout": "",
                    "stderr": "必须提供代码内容或文件路径"
                }
            
            # 获取代码内容
            if file_path:
                with open(file_path, 'r', encoding='utf-8') as f:
                    code = f.read()
                
                # 自动检测语言
                if language == "auto":
                    ext = os.path.splitext(file_path)[1].lower()
                    if ext == '.json':
                        language = 'json'
                    elif ext in ['.py']:
                        language = 'python'
                    elif ext in ['.js']:
                        language = 'javascript'
            
            # 根据语言进行格式化
            if language == 'json':
                formatted_code = self._format_json(code, indent_size)
            elif language == 'python':
                formatted_code = self._format_python(code)
            else:
                # 基础格式化
                formatted_code = self._format_generic(code)
            
            # 如果提供了文件路径，写回文件
            if file_path:
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(formatted_code)
                return {
                    "success": True,
                    "stdout": f"文件已格式化: {file_path}",
                    "stderr": ""
                }
            else:
                return {
                    "success": True,
                    "stdout": formatted_code,
                    "stderr": ""
                }
                
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"代码格式化失败: {str(e)}"
            }

    def _format_json(self, code: str, indent_size: int) -> str:
        """格式化JSON代码"""
        try:
            parsed = json.loads(code)
            return json.dumps(parsed, ensure_ascii=False, indent=indent_size)
        except:
            return code

    def _format_python(self, code: str) -> str:
        """基础Python格式化"""
        try:
            # 这里可以使用black或autopep8进行更好的格式化
            # 现在只做基础的缩进调整
            lines = code.split('\n')
            formatted_lines = []
            indent_level = 0
            
            for line in lines:
                stripped = line.strip()
                if not stripped:
                    formatted_lines.append('')
                    continue
                
                # 减少缩进的情况
                if stripped.startswith(('except', 'elif', 'else', 'finally')):
                    indent_level = max(0, indent_level - 1)
                
                formatted_lines.append('    ' * indent_level + stripped)
                
                # 增加缩进的情况
                if stripped.endswith(':') and not stripped.startswith('#'):
                    indent_level += 1
                
                # 减少缩进的情况（行尾处理）
                if stripped.startswith(('return', 'pass', 'break', 'continue')):
                    indent_level = max(0, indent_level - 1)
            
            return '\n'.join(formatted_lines)
            
        except:
            return code

    def _format_generic(self, code: str) -> str:
        """通用代码格式化"""
        try:
            # 基础的空白符规范化
            lines = code.split('\n')
            formatted_lines = []
            
            for line in lines:
                # 规范化制表符为空格
                formatted = line.expandtabs(4)
                # 移除行尾空白
                formatted = formatted.rstrip()
                formatted_lines.append(formatted)
            
            return '\n'.join(formatted_lines)
            
        except:
            return code